﻿using System.Collections;
using System.Collections.Concurrent;

namespace System.NETool;

public static class CollectionsEx
{
    /// <summary>
    /// 检查并发字典是否不包含指定键
    /// </summary>
    /// <typeparam name="TKey">键类型</typeparam>
    /// <typeparam name="TValue">值类型</typeparam>
    /// <param name="this">并发字典</param>
    /// <param name="key">键</param>
    /// <returns>如果不包含指定键则返回 true，否则返回 false</returns>
    public static bool NotContainsKey<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> @this, TKey key) => !@this.ContainsKey(key);

    /// <summary>
    /// 检查字典是否不包含指定键
    /// </summary>
    /// <typeparam name="TKey">键类型</typeparam>
    /// <typeparam name="TValue">值类型</typeparam>
    /// <param name="this">字典</param>
    /// <param name="key">键</param>
    /// <returns>如果不包含指定键则返回 true，否则返回 false</returns>
    public static bool NotContainsKey<TKey, TValue>(this Dictionary<TKey, TValue> @this, TKey key) => !@this.ContainsKey(key);

    /// <summary>
    /// 检查数组是否为空
    /// </summary>
    /// <param name="this">数组</param>
    /// <returns>如果数组为空或长度为0则返回 true，否则返回 false</returns>
    public static bool IsNullOrEmpty(this IList @this) => @this == null || @this.Count == 0;

    /// <summary>
    /// 检查列表是否包含指定索引
    /// </summary>
    /// <param name="this">列表</param>
    /// <param name="index">索引</param>
    /// <returns>如果包含指定索引则返回 true，否则返回 false</returns>
    public static bool ContainsIndex(this IList @this, int index) => !@this.IsNullOrEmpty() && index >= 0 && index < @this.Count;

    /// <summary>
    /// 检查列表是否不包含指定索引
    /// </summary>
    /// <param name="this">列表</param>
    /// <param name="index">索引</param>
    /// <returns>如果不包含指定索引则返回 true，否则返回 false</returns>
    public static bool NotContainsIndex(this IList @this, int index) => !@this.ContainsIndex(index);

    /// <summary>
    /// 获取列表的第一个元素
    /// </summary>
    /// <typeparam name="T">元素类型</typeparam>
    /// <param name="this">列表</param>
    /// <returns>第一个元素，如果列表为空则返回默认值</returns>
    public static T First<T>(this IList<T> @this) => @this == null || @this.Count == 0 ? default : @this[0];

    /// <summary>
    /// 获取列表的最后一个元素
    /// </summary>
    /// <typeparam name="T">元素类型</typeparam>
    /// <param name="this">列表</param>
    /// <returns>最后一个元素，如果列表为空则返回默认值</returns>
    public static T Last<T>(this IList<T> @this) => @this == null || @this.Count == 0 ? default : @this[^1];

    /// <summary>
    /// 检查集合是否包含所有指定的值
    /// </summary>
    /// <typeparam name="T">集合元素类型</typeparam>
    /// <param name="this">集合</param>
    /// <param name="values">要检查的值</param>
    /// <returns>如果集合包含所有指定的值则返回 true，否则返回 false</returns>
    public static bool ContainsAll<T>(this ICollection<T> @this, params T[] values)
    {
        foreach (T value in values)
        {
            if (!@this.Contains(value))
            {
                return false;
            }
        }

        return true;
    }

    /// <summary>
    /// 检查集合是否包含任意一个指定的值
    /// </summary>
    /// <typeparam name="T">集合元素类型</typeparam>
    /// <param name="this">集合</param>
    /// <param name="values">要检查的值</param>
    /// <returns>如果集合包含任意一个指定的值则返回 true，否则返回 false</returns>
    public static bool ContainsAny<T>(this ICollection<T> @this, params T[] values)
    {
        foreach (T value in values)
        {
            if (@this.Contains(value))
            {
                return true;
            }
        }

        return false;
    }

    /// <summary>
    /// 检查字典是否包含所有指定的键
    /// </summary>
    /// <typeparam name="TKey">键类型</typeparam>
    /// <typeparam name="TValue">值类型</typeparam>
    /// <param name="this">字典</param>
    /// <param name="keys">要检查的键</param>
    /// <returns>如果字典包含所有指定的键则返回 true，否则返回 false</returns>
    public static bool ContainsAllKey<TKey, TValue>(this IDictionary<TKey, TValue> @this, params TKey[] keys)
    {
        foreach (TKey value in keys)
        {
            if (!@this.ContainsKey(value))
            {
                return false;
            }
        }

        return true;
    }

    /// <summary>
    /// 检查字典是否包含任意一个指定的键
    /// </summary>
    /// <typeparam name="TKey">键类型</typeparam>
    /// <typeparam name="TValue">值类型</typeparam>
    /// <param name="this">字典</param>
    /// <param name="keys">要检查的键</param>
    /// <returns>如果字典包含任意一个指定的键则返回 true，否则返回 false</returns>
    public static bool ContainsAnyKey<TKey, TValue>(this IDictionary<TKey, TValue> @this, params TKey[] keys)
    {
        foreach (TKey value in keys)
        {
            if (@this.ContainsKey(value))
            {
                return true;
            }
        }

        return false;
    }

    /// <summary>
    /// 检查枚举是否包含所有指定的值
    /// </summary>
    /// <typeparam name="T">枚举元素类型</typeparam>
    /// <param name="this">枚举</param>
    /// <param name="values">要检查的值</param>
    /// <returns>如果枚举包含所有指定的值则返回 true，否则返回 false</returns>
    public static bool ContainsAll<T>(this IEnumerable<T> @this, params T[] values)
    {
        T[] list = @this.ToArray();
        foreach (T value in values)
        {
            if (!list.Contains(value))
            {
                return false;
            }
        }

        return true;
    }

    /// <summary>
    /// 检查枚举是否包含任意一个指定的值
    /// </summary>
    /// <typeparam name="T">枚举元素类型</typeparam>
    /// <param name="this">枚举</param>
    /// <param name="values">要检查的值</param>
    /// <returns>如果枚举包含任意一个指定的值则返回 true，否则返回 false</returns>
    public static bool ContainsAny<T>(this IEnumerable<T> @this, params T[] values)
    {
        T[] list = @this.ToArray();
        foreach (T value in values)
        {
            if (list.Contains(value))
            {
                return true;
            }
        }

        return false;
    }
}
